/*
 * Copyright (c) 2016. 杭州端点网络科技有限公司.  All rights reserved.
 */

package com.jiantong.user.impl.service;

import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import com.jiantong.common.util.MD5Util;
import com.jiantong.user.enums.LoginType;
import com.jiantong.user.impl.dao.UserDao;
import com.jiantong.user.impl.dao.UserProfileDao;
import com.jiantong.user.model.User;
import com.jiantong.user.model.UserProfile;
import com.jiantong.user.service.UserReadService;
import io.terminus.boot.rpc.common.annotation.RpcProvider;
import io.terminus.common.model.PageInfo;
import io.terminus.common.model.Paging;
import io.terminus.common.model.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Author:  <a href="mailto:i@terminus.io">jlchen</a>
 * Date: 2016-01-28
 */
@Service
@Slf4j
@RpcProvider
public class UserReadServiceImpl implements UserReadService<User> {

    private final UserDao userDao;
    private final UserProfileDao userProfileDao;

    @Autowired
    public UserReadServiceImpl(UserDao userDao, UserProfileDao userProfileDao) {
        this.userDao = userDao;
        this.userProfileDao = userProfileDao;
    }

    /**
     * 根据用户id查询用户信息
     *
     * @param id 用户id
     * @return 对应的用户id
     */
    @Override
    public Response<User> findById(Long id) {
        try {
            User user = userDao.findById(id);
            if (user == null) {
                log.error("user(id={}) is not found", id);
                return Response.fail("user.not.found");
            }
            return Response.ok(user);
        } catch (Exception e) {
            log.error("failed to find user(id={}), cause:{}", id, Throwables.getStackTraceAsString(e));
            return Response.fail("user.find.fail");
        }
    }

    /**
     * 根据一组用户id查询一个List<User>
     *
     * @param listId
     * @return List<User>
     */
    @Override
    public Response<List<User>> findByIds(List<Long> listId) {
        try {
            List<User> userList = userDao.findByIds(listId);
            if (userList == null){
                log.error("listUser (ids = {}) is not found",listId);
                return Response.fail("userList.not.found");
            }
            return Response.ok(userList);
        } catch (Exception e){
            log.error("failed to find userList (ids = {}),cause : {}",listId,Throwables.getStackTraceAsString(e));
            return Response.fail("userList.find.fail");
        }
    }

    /**
     * 根据用户标识查询客户
     *
     * @param loginId   用户标识
     * @param loginType 用户标志类型
     * @return 对应的用户
     */
    @Override
    public Response<User> findBy(String loginId, LoginType loginType) {
        try {
            User user;
            switch (loginType) {
                case NAME:
                    user = userDao.findByName(loginId);
                    break;
                case EMAIL:
                    user = userDao.findByEmail(loginId);
                    break;
                case MOBILE:
                    user = userDao.findByMobile(loginId);
                    break;
                default:
                    return Response.fail("user.not.found");
            }
            if (user == null) {
                log.error("user(loginId={}, loginType={}) not found", loginId, loginType);
                return Response.fail("user.not.found");
            }
            return Response.ok(user);
        } catch (Exception e) {
            log.error("failed to find user(loginId={}, loginType={}), cause:{}",
                    loginId, loginType, Throwables.getStackTraceAsString(e));
            return Response.fail("user.find.fail");
        }
    }

    /**
     * 用户登录, 首先检查用户是否存在, 其次检查状态是否正常, 最后检查密码是否匹配
     *
     * @param loginId   登录id
     * @param password  登录密码
     * @param loginType 登录类型
     * @return 如果登录成功, 则返回对应的用户
     */
    @Override
    public Response<User> login(String loginId, String password, LoginType loginType) {
        Response<User> rUser = findBy(loginId, loginType);
        if (!rUser.isSuccess()) {
            return rUser;
        }
        User user = rUser.getResult();
        if (user.getStatus() < 0) {
            log.error("user(loginId={}, loginType={})'s status is {}, login forbidden ",
                    loginId, loginType, user.getStatus());
            switch (user.getStatus()) {
                case -1:
                    return Response.fail("user.status.locked");
                case -2:
                    return Response.fail("user.status.frozen");
                case -3:
                    return Response.fail("user.status.deleted");
                default:
                    return Response.fail("user.status.abnormal");
            }
        }
        if (!MD5Util.match(password, user.getPassword())) {
            log.error("user(loginId={}, loginType={})'s password mismatch, login failed", loginId, loginType);
            return Response.fail("user.password.mismatch");
        }
        return rUser;
    }

    @Override
    public Response<Boolean> checkExist(String loginId, LoginType loginType) {
        try {
            User user;
            switch (loginType) {
                case NAME:
                    user = userDao.findByName(loginId);
                    break;
                case EMAIL:
                    user = userDao.findByEmail(loginId);
                    break;
                case MOBILE:
                    user = userDao.findByMobile(loginId);
                    break;
                default:
                    return Response.fail("user.unknown.login.type");
            }
            return Response.ok(user != null);
        } catch (Exception e) {
            log.error("check user existing failed, loginId={}, loginType={}, cause:{}",
                    loginId, loginType, Throwables.getStackTraceAsString(e));
            return Response.fail("user.find.fail");
        }
    }

    @Override
    public Response<UserProfile> findProfileByUserId(Long userId) {
        Response<UserProfile> resp = new Response<UserProfile>();
        try {
            UserProfile profile = userProfileDao.findByUserId(userId);
            if (profile == null){
                return Response.ok(new UserProfile());
            }
            resp.setResult(profile);
        } catch (Exception e){
            log.error("failed to find current login user(id={}), cause: {}", userId, Throwables.getStackTraceAsString(e));
            resp.setError("user.profile.find.fail");
        }
        return resp;
    }

    /**
     * 根据userId查询用户
     *
     * @param userId
     * @return user
     */
    @Override
    public Response<User> findUserByUserId(Long userId) {
        try {
            User user = userDao.findById(userId);
            if (user == null) {
                log.error("user(userId={}) is not found", userId);
                return Response.fail("user.not.found");
            }
            return Response.ok(user);
        } catch (Exception e) {
            log.error("failed to find user(userId={}), cause:{}", userId, Throwables.getStackTraceAsString(e));
            return Response.fail("user.find.fail");
        }
    }

    /**
     * 根据名字关键字模糊查询
     *
     * @param keyword
     * @return ids
     */
    @Override
    public Response<List<Long>> findIdsByName(String keyword) {

        try {
            List<User> users = userDao.findIdsByName(keyword);
            if (users == null) {
                return Response.fail("uesrId.not.found");
            }
            List<Long> longs = new ArrayList<>();
            for (int i=0;i<users.size();i++){
                longs.set(i,users.get(i).getId());
            }
            return Response.ok(longs);
        }catch (Exception e){
            log.error("failed to find user(id={}), cause:{}", keyword, Throwables.getStackTraceAsString(e));
            return Response.fail("ids.find.fail");
        }
    }

    /**
     * 根据关键字对应名字分页模糊查询
     *
     * @param keyword
     * @return list<User>
     */
    @Override
    public Response<Paging<User>> findByKeywordName(Integer pageNo, Integer pageSize, String keyword) {

        try {
            PageInfo pageInfo = new PageInfo(pageNo, pageSize);
            Map<String, Object> criteria = Maps.newHashMap();
            if (keyword != null) {
                criteria.put("keyword", keyword);
            }
            return Response.ok(userDao.pagingFindBykeyword(pageInfo.getOffset(), pageInfo.getLimit(), criteria));
        } catch (Exception e) {
            log.error("failed to find user(keyword={}), cause:{}", keyword, Throwables.getStackTraceAsString(e));
            return Response.fail("user.find.fail");
        }

    }

    public Response<List<User>> selectAlUser(Map criteria){
        try {
            return Response.ok(userDao.selectAllUser(criteria));
        } catch (Exception e) {
            log.error("failed to find user(keyword={}), cause:{}", Throwables.getStackTraceAsString(e));
            return Response.fail("user.find.fail");
        }

    }

 public Response<List<Long>> selectIds(Map criteria){
        try {
            return Response.ok(userDao.selectIds(criteria));
        } catch (Exception e) {
            log.error("failed to find user(keyword={}), cause:{}", Throwables.getStackTraceAsString(e));
            return Response.fail("user.find.fail");
        }

    }


}
